package org.example.component;

import org.example.service.UserService;
import org.example.service.impl.StudentServiceImpl;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 帮我们创建代理对象一个工具处理类
 *
 * 需求：为目标（被）对象 创建代理对象并且实现功能增强（处理事务）
 */
public  class CGLibDynamicProxyHandler {

    //被代理的对象
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //要增强的功能(事务管理器方法)
    private TransactionManagerHandler txManager;

    public void setTxManager(TransactionManagerHandler txManager) {
        this.txManager = txManager;
    }

    /**
     * 返回被代理对象的方法
     * @return
     */
    public UserService getProxy() {

       //创建Enhancer
        Enhancer enhancer = new Enhancer();
        //设置类加载器
        enhancer.setClassLoader(target.getClass().getClassLoader());
        //设置被代理对象的字节码
        enhancer.setSuperclass(target.getClass());

        //处理器
        enhancer.setCallback(new org.springframework.cglib.proxy.InvocationHandler() {
            /**
             *
             * @param proxy 代理对象
             *
             * @param method 被代理对象的方法
             *
             * @param args 被代理方法的参数
             *
             * @return 被代理对象方法执行以后返回的结果
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    txManager.begin();
                    //使用反射执行被代理对象的方法.核心业务逻辑方法
                    result = method.invoke(target, args);

                    txManager.commit();
                } catch (Exception e) {
                    txManager.rollback();
                    throw new RuntimeException(e);
                } finally {
                    txManager.close();
                }
                return result;
            }
        });
        //创建代理对象
        Object o = enhancer.create();

        return (UserService) o;
    }



}


